/********************************************************************
文件名称:   rngLib.h

文件功能:   环形数组库

文件说明:   该函数库从VxWorks rngLib.c下移植,当在单片机下使用时可能会申请失败
            可以通过在单片机启动汇编文件中修改堆大小解决。

当前版本:   V1.0

修改记录:   2016-10-27  V1.0    王  明  创建
********************************************************************/
#ifndef __INCrngLibh
#define __INCrngLibh

/* define */
#define bcopy(s, d, n)  memcpy ((d), (s), (n))
#define min(a,b)        ((a) < (b) ? (a) : (b))
#define FAST            register
#define TRUE            (1)
#define FALSE           (0)

/* typedefs */
typedef struct          /* RING - ring buffer */
{
    size_t pToBuf;      /* offset from start of buffer where to write next */
    size_t pFromBuf;    /* offset from start of buffer where to read next */
    size_t bufSize;     /* size of ring in bytes */
    char *buf;          /* pointer to start of buffer */
} RING;

typedef RING *RING_ID;

typedef int BOOL;

/*
 * The following macros are designed to do various operations on
 * the RING object.  By using them, users can avoid having to know
 * the structure of RING.  However they are intended to be very
 * efficient and this is why they are macros in the first place.
 * In general the parameters to them should be register variables
 * for maximum efficiency.
 */

/*******************************************************************************
*
* RNG_ELEM_GET - get one character from a ring buffer
*
* This macro gets a single character from the specified ring buffer.
* Must supply temporary variable (register long) 'fromP'.
*
* RETURNS: 1 if there was a char in the buffer to return, 0 otherwise
*
* NOMANUAL
*/

#define RNG_ELEM_GET(ringId, pCh, fromP)        \
    (                       \
    fromP = (ringId)->pFromBuf,         \
    ((ringId)->pToBuf == fromP) ?       \
    0                   \
    :                       \
    (                   \
    *pCh = (ringId)->buf[fromP],        \
    (ringId)->pFromBuf = ((++fromP == (ringId)->bufSize) ? 0 : fromP), \
    1                   \
    )                   \
    )

/*******************************************************************************
*
* RNG_ELEM_PUT - put one character into a ring buffer
*
* This macro puts a single character into the specified ring buffer.
* Must supply temporary variable (register long) 'toP'.
*
* RETURNS: 1 if there was room in the buffer for the char, 0 otherwise
*
* NOMANUAL
*/

#define RNG_ELEM_PUT(ringId, ch, toP)       \
    (                       \
    toP = (ringId)->pToBuf,         \
    (toP == (ringId)->pFromBuf - 1) ?       \
    0                   \
    :                       \
    (                   \
        (toP == (ringId)->bufSize - 1) ?    \
        (                   \
        ((ringId)->pFromBuf == 0) ?     \
        0               \
        :                   \
        (               \
        (ringId)->buf[toP] = ch,    \
        (ringId)->pToBuf = 0,       \
        1               \
        )               \
        )                   \
    :                   \
        (                   \
        (ringId)->buf[toP] = ch,        \
        (ringId)->pToBuf++,         \
        1                   \
        )                   \
    )                   \
    )

#ifdef __cplusplus
extern "C" {
#endif

extern BOOL     rngIsEmpty (RING_ID ringId);
extern BOOL     rngIsFull (RING_ID ringId);
extern RING_ID  rngCreate (size_t nbytes);
extern size_t   rngBufGet (RING_ID rngId, char *buffer, size_t maxbytes);
extern size_t   rngBufPut (RING_ID rngId, char *buffer, size_t nbytes);
extern size_t   rngFreeBytes (RING_ID ringId);
extern size_t   rngNBytes (RING_ID ringId);
extern void     rngDelete (RING_ID ringId);
extern void     rngFlush (RING_ID ringId);
extern void     rngMoveAhead (RING_ID ringId, size_t n);
extern void     rngPutAhead (RING_ID ringId, char byte, size_t offset);

#ifdef __cplusplus
}
#endif

#endif /* __INCrngLibh */
